package net.WMisiedjan.WirelessRedstone.Configuration;

import java.beans.Beans;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.filechooser.FileFilter;

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

import net.WMisiedjan.WirelessRedstone.StackableLogger;
import net.WMisiedjan.WirelessRedstone.WirelessChannel;
import net.WMisiedjan.WirelessRedstone.WirelessReceiver;
import net.WMisiedjan.WirelessRedstone.WirelessRedstone;
import net.WMisiedjan.WirelessRedstone.WirelessTransmitter;

public class WirelessRedstoneConf extends WirelessConfiguration {
	private StackableLogger logger;
	private File dataFolder;
	private File configFile;

	public WirelessRedstoneConf(File dataFolder) {
		super(new File(dataFolder, "settings.yml"));
		this.configFile = new File(dataFolder, "settings.yml");
		this.dataFolder = dataFolder;
		if (this.root == null) {
			this.root = new HashMap<String, Object>();
		}
		logger = WirelessRedstone.getLogger();

		Constructor constructor = new Constructor();
		constructor.addTypeDescription(new TypeDescription(
				WirelessChannel.class, "!WirelessChannel"));
		Representer representer = new Representer();
		Tag taggy = new Tag("!WirelessChannel");
		representer.addClassTag(
				net.WMisiedjan.WirelessRedstone.WirelessChannel.class, taggy);
		DumperOptions options = new DumperOptions();
		options.setIndent(4);
		options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
		yaml = new Yaml(constructor, representer, options);
	}

	@Override
	public void load() {
		this.configFile = configFile.getAbsoluteFile();
		if (!configFile.getParentFile().exists()) {
			if (!configFile.getParentFile().mkdirs()) {
				logger.severe("Error creating folders for Configuration.");
			}
		}
		if (!configFile.exists()) {
			try {
				File oldconf = new File(dataFolder, "config.yml");
				if (oldconf.exists()) {
					oldconf.renameTo(configFile);
					this.load();
					return;
				}
				logger.info("Creating empty config file. Loading default settings.");
				if (!configFile.createNewFile()) {
					logger.severe("Failed to create config file.");
				}
				GenerateDefaults();
			} catch (IOException ex) {
				logger.severe("Failed to create config file.");
			}
		}

		super.load();
		if (this.root == null) {
			this.root = new HashMap<String, Object>();
		}

		if (this.getProperty("WirelessObjects") != null) {
			ConvertOldToNew();
		}
	}

	private boolean ConvertOldToNew() {
		this.logger
				.info("Converting old configuration to new configuration...");
		Object oldObject = this.getProperty("WirelessObjects");
		Hashtable<String, WirelessChannel> newconf = new Hashtable<String, WirelessChannel>();
		if (oldObject instanceof Map<?, ?>) {
			Map<String, Object> oldchannelist = (Map<String, Object>) this
					.getProperty("WirelessObjects");

			for (Map.Entry<String, Object> oldchannel : oldchannelist
					.entrySet()) {
				WirelessChannel channel = new WirelessChannel();
				channel.setName(oldchannel.getKey());
				this.logger.info("Channel: " + oldchannel.getKey());

				if (!(oldchannel.getValue() instanceof Map)) {
					return false;
				}

				Map<Object, Object> signpoints = (Map<Object, Object>) oldchannel
						.getValue();
				for (Map.Entry<Object, Object> signpoint : signpoints
						.entrySet()) {
					this.logger.info("Found type:" + signpoint.getKey());
					if (signpoint.getKey().toString()
							.startsWith("Transmitters")) {
						if (signpoint.getValue() instanceof String) {
							this.logger.info("Found Transmitter with thingies:"
									+ signpoint.getValue());
							WirelessTransmitter newtransmitter = new WirelessTransmitter();
							String[] args = signpoint.getValue().toString()
									.split(",");
							newtransmitter.setWorld(args[3]);
							channel.addOwner(args[4]);
							newtransmitter.setOwner(args[4]);
							newtransmitter.setX(Integer.parseInt(args[0]));
							newtransmitter.setY(Integer.parseInt(args[1]));
							newtransmitter.setZ(Integer.parseInt(args[2]));
							channel.addTransmitter(newtransmitter);
						}
						for (String data : (List<String>) signpoint.getValue()) {
							this.logger.info("Found Transmitter with thingies:"
									+ data);
							WirelessTransmitter newtransmitter = new WirelessTransmitter();
							String[] args = data.split(",");
							newtransmitter.setWorld(args[3]);
							channel.addOwner(args[4]);
							newtransmitter.setOwner(args[4]);
							newtransmitter.setX(Integer.parseInt(args[0]));
							newtransmitter.setY(Integer.parseInt(args[1]));
							newtransmitter.setZ(Integer.parseInt(args[2]));
							channel.addTransmitter(newtransmitter);
						}
					} else if (signpoint.getKey().toString()
							.startsWith("Receivers")) {
						if (signpoint.getValue() instanceof String) {
							this.logger.info("Found Receiver with thingies:"
									+ signpoint.getValue());
							WirelessReceiver newreceiver = new WirelessReceiver();
							String[] args = signpoint.getValue().toString()
									.split(",");
							newreceiver.setWorld(args[3]);
							channel.addOwner(args[4]);
							newreceiver.setOwner(args[4]);
							newreceiver.setX(Integer.parseInt(args[0]));
							newreceiver.setY(Integer.parseInt(args[1]));
							newreceiver.setZ(Integer.parseInt(args[2]));
							channel.addReceiver(newreceiver);
						} else {
							for (String data : (List<String>) signpoint
									.getValue()) {
								this.logger
										.info("Found Receiver with thingies:"
												+ data);
								WirelessReceiver newreceiver = new WirelessReceiver();
								String[] args = data.split(",");
								newreceiver.setWorld(args[3]);
								channel.addOwner(args[4]);
								newreceiver.setOwner(args[4]);
								newreceiver.setX(Integer.parseInt(args[0]));
								newreceiver.setY(Integer.parseInt(args[1]));
								newreceiver.setZ(Integer.parseInt(args[2]));
								channel.addReceiver(newreceiver);
							}
						}
					}
				}

				newconf.put(channel.getName(), channel);
			}

		}

		this.setProperty("WirelessChannels", newconf);
		this.removeProperty("WirelessObjects");
		this.removeProperty("AllowedWorlds");
		GenerateDefaults();
		this.save();
		return false;
	}

	private void GenerateDefaults() {
		this.setProperty("LogLevel", Level.INFO.getName().toUpperCase());
		this.setProperty("cancelChunkUnloads", true);
		this.setProperty("cancelChunkUnloadRange", 4);
		this.save();
	}

	public boolean isCancelChunkUnloads() {
		return this.getBoolean("cancelChunkUnloads", true);
	}

	public int getChunkUnloadRange() {
		return this.getInt("cancelChunkUnloadRange", 4);
	}

	public Level getLogLevel() {
		return Level.parse(this.getString("LogLevel"));
	}
}
